package com.zst.dollars.handler.server;

import com.zst.dollars.common.Consts;
import com.zst.dollars.entity.connection.ClientDisconnectAnnounceMessage;
import com.zst.dollars.entity.connection.ServerConnectResultMessage;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.channel.group.ChannelGroup;
import io.netty.util.AttributeKey;

import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 服务端用于处理客户端的连接事件的Handler
 */
public class ClientConnectionHandler extends ChannelInboundHandlerAdapter {
    private ConcurrentHashMap<String, String> clientTokenUsernameMap;
    private ChannelGroup channelGroup;

    public ClientConnectionHandler(ConcurrentHashMap<String, String> map, ChannelGroup channelGroup){
        this.clientTokenUsernameMap = map;
        this.channelGroup = channelGroup;
    }

    /**
     * 处理客户端连接建立事件，生成并保存clientToken，添加channel到group
     * @param ctx
     * @throws Exception
     */
    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        String clientToken = UUID.randomUUID().toString().replaceAll("-", "");
        ctx.channel().attr(Consts.tokenKey).set(clientToken);
        ctx.channel().attr(Consts.keepAliveCount).set(new AtomicInteger(0));
        clientTokenUsernameMap.put(clientToken, "");
        channelGroup.add(ctx.channel());
        ServerConnectResultMessage message = new ServerConnectResultMessage(clientToken);
        ctx.writeAndFlush(message);
        ctx.fireChannelActive();
    }

    /**
     * 处理客户端连接断开事件，通知其他客户端有人断开
     * @param ctx
     * @throws Exception
     */
    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        //从map中移除token，并且从channelGroup中移除channel
        String username = clientTokenUsernameMap.get(ctx.channel().attr(Consts.tokenKey).get());
        clientTokenUsernameMap.remove(ctx.channel().attr(Consts.tokenKey));
        channelGroup.remove(ctx.channel());

        //通知其他channel，有人断开连接
        ClientDisconnectAnnounceMessage disconnectAnnounceMessage = new ClientDisconnectAnnounceMessage(username);
        channelGroup.writeAndFlush(disconnectAnnounceMessage);
    }
}
